const menuList = [
    {
        name: '凉拌SAN',
        price: 6,
        doingTime:100,
        waitTime: 100,
        eatTime: 100,
    },
    {
        name: '冷切DOM',
        price: 4,
        doingTime:100,
        waitTime: 100,
        eatTime: 100
    },
    {
        name: 'UL炖LI',
        price: 12,
        doingTime:500,
        waitTime: 100,
        eatTime: 100
    },
    {
        name: '红烧HEAD',
        price: 15,
        doingTime:200,
        waitTime: 100,
        eatTime: 100,
    },
    {
        name: '酥炸ECharts',
        price: 18,
        doingTime: 600,
        waitTime: 100,
        eatTime: 100
    },
    {
        name: '炙烤CSS',
        price: 16,
        doingTime: 300,
        waitTime: 100,
        eatTime: 100
    },
    {
        name: '清蒸DIV',
        price: 12,
        doingTime: 100,
        waitTime: 100,
        eatTime: 100
    },
    {
        name: '鲜榨flex',
        price: 5,
        doingTime: 80,
        waitTime: 50,
        eatTime: 100
    },
    {
        name: '小程序奶茶',
        price: 6,
        doingTime: 80,
        waitTime: 100,
        eatTime: 100
    }
]

const cusCandidate = [
    {
        name: 'ZHAO',
        status: 'possible',
        avatar: './img/figure_customer_1.png'
    },
    {
        name: 'QIAN',
        status: 'possible',
        avatar: './img/figure_customer_2.png'
    },
    {
        name: 'SUN',
        status: 'possible',
        avatar: './img/figure_customer_3.png'
    },
    {
        name: 'LI',
        status: 'possible',
        avatar: './img/figure_customer_4.png'
    },
    {
        name: 'ZHOU',
        status: 'possible',
        avatar: './img/figure_customer_5.png'
    },
    {
        name: 'WU',
        status: 'possible',
        avatar: './img/figure_customer_6.png'
    },
    {
        name: 'ZHENG',
        status: 'possible',
        avatar: './img/figure_customer_7.png'
    }
]



class Restaurant {
    constructor() {
        this.customers = []
        this.chefs = []
        this.tables = [
            // {cus, ordered: []}
            null, null, null, null
        ]
        this.waitNum = 0

        let operations = {}
        // 增加顾客
        operations.addCustomer = () => {
            this.customers.push(new Customer())
        }
        // 点菜
        operations.orderDishes = (tableID, info) => {
            this.tables[tableID].cus = info.cus
            this.tables[tableID].ordered = info.ordered
        }
        // 删除超时的菜
        operations.removeDishes = (tableID, dishID) => {}
        // 顾客离开
        operations.leave = ( cus, tableID ) => {
            this.tables[tableID] = null
            this.customers.filter( item => item !== cus)
        }
        // 顾客结账
        operations.checkout = ( cus, tableID ) => {
            this.tables[tableID] = null
            // 更新money
            this.customers.filter( item => item !== cus)
        }


        // 厨师获取待烹饪的菜
        operations.getWaitDish = ()  => {
            // 如果有，修改厨师状态
            for (let i = 0; i < 4; i++) {
                if (this.tables[i] && this.tables[i].ordered.length) {
                    return [i, this.tables[i].ordered.shift()]
                }
            }
            return null
        }
        // 烹饪结束，等待上菜
        operations.serveDish = (tableID, dishID) => {
            let dishNode = document.querySelector(`.customer:nth-child(${tableID + 1}) [data-dish-id="${dishID}"]`)
            dishNode.insertAdjacentHTML('beforeend', `
                <div class="dish-serve">
                    <img src="./img/icon_serve.png" alt="">
                </div>`
            )
            let serveBtn = dishNode.children[1]
            serveBtn.onclick = function () {
                let {waitList} = tables[tableID].cus.cusInfo
                waitList.filter(cur => cur.dishID !== dishID)
            }
        }
        // 删除厨师
        operations.removeChef = ( chef ) => {
            this.chefs.filter( item => item !== chef)
        }
        this.operations = operations
    }
    receiveMessage = (...theArgs) => {
        let message = Array.prototype.shift.call( theArgs )
        this.operations[message].apply(this, theArgs)
    }
    addChef = () => {
        let chef = new Chef()
        chef.init(this.chefs.length)
        this.chefs.push(chef)
    }
}
const restaurant = new Restaurant()



class FreeState {
    constructor(chef) {
        this.chef = chef
    }
    enter = () => {
        this.chef.chefNode.className = "chef-avatar chef-free"
    }
    run = () => {
        // 如果获取到订单，立即转入做饭状态
        let res = restaurant.receiveMessage('getWaitDish')
        if (res) {
            let [tableID, dishID] = res
            Object.assign(this.chef.chefInfo, {cookFor: tableID, dishID})
            this.chef.setState(this.chef.cookState)
        }
    }
    leave = () => {}
}
class CookState {
    constructor(chef) {
        this.chef = chef
    }
    enter = () => {
        let {chefNode} = this.chef
        let {dishID} = this.chef.chefInfo
        chefNode.className = "chef-avatar chef-cooking"
        chefNode.insertAdjacentHTML('afterend', `
            <div class="chef-dish dish-cooking">${menuList[dishID].name}</div>
        `)

    }
    run = () => {}
    leave = () => {}
}
class FinishState {
    constructor(chef) {
        this.chef = chef
    }
    enter  = () => {
        let res = `<div class="chef">
            <div class="chef-item">
            <div class="chef-avatar chef-finished">
            <img src="./img/figure_chef.png" alt="">
            <img class="chef-serve" src="./img/icon_serve.png" alt="">
            <div class="chef-dish dish-finished">红烧HEAD</div>
            </div>
            </div>
            </div>`
    }
    run = () => {}
    leave = () => {
        // 重置烹饪信息
        Object.assign(this.chef.chefInfo, {
            cookFor: -1,
            dishID: -1,
            alreadyCook: 0
        })
    }
}
class Chef {
    constructor() {
        this.freeState = new FreeState(this)
        this.cookState = new CookState(this)
        this.finishState = new FinishState(this)
    }
    init(chefID) {
        this.chefInfo = {
            id: chefID,
            cookFor: -1,
            dishID: -1,
            alreadyCook: 0
        }
        let chefArea = document.querySelector('.chef-area')
        chefArea.insertAdjacentHTML('beforeend', `
            <div class="chef">
                <div class="chef-item">
                    <div class="chef-avatar chef-free">
                        <img src="./img/figure_chef.png" alt="">
                    </div>
                </div>
            </div>
        `)
        this.chefNode = document.querySelector(`.chef:nth-child(${chefID + 1}) .chef-avatar`)
        this.curState = this.freeState
    }
    setState(newState) {
        let args = this.curState.leave()
        this.curState = newState
        this.curState.enter(args)
    }
}



// 创建customer
// 等待
class WaitState {
    constructor( cus ) {
        this.cus = cus
        this.waitArea = document.querySelector('.wait-area')
        this.waitNode = null
    }
    enter = () => {
        let { avatar } = this.cus.cusInfo
        this.waitNode = document.createElement('div')
        this.waitNode.className = 'wait-item'
        this.waitNode.innerHTML = `
            <div class="wait-avatar">
                <img src="${avatar}" alt="">
            </div>
            <div class="wait-process">等位中</div>
        `
        this.waitArea.appendChild(this.waitNode)
        // 点击用户头像，切换状态
        this.waitNode.addEventListener('click', () => {
            for (let table of restaurant.tables) {
                if (!table) {
                    this.cus.setState(this.cus.orderState)
                    return
                }
            }
            console.log('没有空座位了')
        })
    }
    run = () => {
        let { timeToLeave } = this.cus.cusInfo
        let process = this.waitNode.children[1]
        process.style.background = 'linear-gradient(to right, #006dd9 ' +
            (100 - timeToLeave) + '%, #2693ff ' +
            (100 - timeToLeave) + '%)'
        timeToLeave--
        this.cus.cusInfo.timeToLeave = timeToLeave
        if (timeToLeave <= 0) {
            this.waitArea.removeChild(this.waitNode)
            this.cus.destory()
        }
    }
    leave = () => {
        this.waitArea.removeChild(this.waitNode)
    }
}
class OrderState {
    constructor( cus, menuHandler ) {
        this.cus = cus
        this.menuHandler = menuHandler
        this.dishes = null
    }
    enter = () => {
        const confirmBtn = document.querySelector('.tip-menu-confirm')
        const abandonBtn = document.querySelector('.tip-menu-abandon')
        let { name, avatar, waitList } = this.cus.cusInfo
        this.menuHandler.show(name, avatar)
        confirmBtn.onclick = () => {
            if (this.menuHandler.check()) {
                this.cus.setState(this.cus.serveState)
            }
        }
        abandonBtn.onclick = () => {
            this.menuHandler.close()
            this.cus.destory()
        }
    }
    leave = () => {
        let orders = this.menuHandler.statistics()
        Object.assign(this.cus.cusInfo, orders)
        this.menuHandler.close()
    }
}
class ServeState {
    constructor( cus ) {
        this.cus = cus
        this.cusNode = null
    }
    enter = () => {
        let table = -1
        let {avatar, ordered} = this.cus.cusInfo
        // 初始化等菜列表
        let waitList = []
        for (let dishID of ordered) {
            waitList.push({dishID, alreadyWait: 0})
        }
        this.cus.cusInfo.waitList = waitList

        // 选择餐桌
        let tables = restaurant.tables
        for (let idx in tables) {
            if (!tables[idx]) {
                tables[idx] = this
                table = idx * 1
                break
            }
        }
        this.cus.cusInfo.table = table // 更新顾客所属餐桌ID
        restaurant.receiveMessage('orderDishes',
            table,
            {cus: this.cus, ordered: ordered.slice()}
        )

        // 将顾客信息渲染到餐桌上
        this.cusNode = document.querySelector(`.customer:nth-child(${table + 1})  .customer-item`)
        this.cusNode.className = "customer-item customer-wait"
        this.cusNode.innerHTML = `      
            <div class="customer-avatar">
                <img class="customer-figure" src="${avatar}" alt="">
                <div class="customer-dishes"></div>
            </div>
        `
        // 将菜品信息渲染到餐桌上
        let dishesWrap = document.querySelector(`.customer:nth-child(${table + 1}) .customer-dishes`)
        for (let {dishID} of waitList) {
            dishesWrap.insertAdjacentHTML('beforeend', `
                <div class="customer-dish-item dish-wait" data-dish-id="${dishID}">${menuList[dishID].name}</div>
            `)
        }
        // setTimeout(() => {this.cus.setState(this.cus.payState)}, 1000)
    }
    run = () => {
        let {table, ordered, waitList, missList, eatList} = this.cus.cusInfo
        // 渲染菜品等待进度
        for (let i = 0; i < waitList.length; i++) {
            let process = 0
            let dish = waitList[i]
            let dishNode = document.querySelector(`.customer:nth-child(${table + 1}) [data-dish-id="${dish.dishID}"]`)
            dish.alreadyWait++
            process = Math.floor((dish.alreadyWait / menuList[dish.dishID].waitTime) * 100)
            dishNode.setAttribute("style",
                `background: linear-gradient(to right, #b20000 ${process}%, #ff2020 ${process}%)`
            );
            if (process >= 100) {
                dishNode.className = 'customer-dish-item dish-miss'
            }
        }
        // 删除等待超时的菜品
        waitList = waitList.filter(cur => {
            if (cur.alreadyWait >= menuList[cur.dishID].waitTime) {
                restaurant.receiveMessage('removeDishes', table, cur.dishID)
                missList.push(cur.dishID)
                return false
            } else {
                return true
            }
        })
        this.cus.cusInfo.waitList = waitList
        // 切换顾客状态
        if (!waitList.length) {
            if(missList.length === ordered.length) {
                this.cus.setState(this.cus.comfortState)
            } else {
                this.cus.setState(this.cus.eatState)
            }
        }
    }
    leave = () => {

    }
}
class EatState {
    constructor( cus ) {
        this.cus = cus
    }
    enter = () => {
        let {table, eatList} = this.cus.cusInfo
        for (let i = 0; i < waitList.length; i++) {
            let process = 0
            let dish = waitList[i]
            let dishNode = document.querySelector(`.customer:nth-child(${table + 1}) [data-dish-id="${i}"]`)
            dish.alreadyWait++
            process = Math.floor((dish.alreadyWait / menuList[dish.dishID].waitTime) * 100)
            dishNode.setAttribute("style",
                `background: linear-gradient(to right, #b20000 ${process}%, #ff2020 ${process}%)`
            );
            if (process >= 100) {
                dishNode.className = 'customer-dish-item dish-miss'
            }
        }
        // 渲染吃饭进度
    }
    leave = () => {}
}
class ComfortState {
    constructor( cus ) {
        this.cus = cus
    }
    enter = () => {
        this.table = this.cus.cusInfo.table
        this.cusNode = document.querySelector(`.customer:nth-child(${this.table + 1})  .customer-item`)

        let iconFather = this.cusNode.children[0]
        let icon = iconFather.children[2]
        this.cusNode.className = 'customer-item customer-miss'
        if (icon) {
            iconFather.removeChild(icon)
        }
        iconFather.insertAdjacentHTML('beforeend', `
            <img class="customer-icon customer-heart" src="./img/icon_heart.png" alt="">
        `)
        this.cusNode.children[0].onclick = () => {
            this.cusNode.children[0].innerHTML = ''
            this.cusNode.className = 'customer-item'
            restaurant.tables[this.table]= null  // 删除顾客信息
            this.cus.destory()
        }
    }
    leave = () => {}
}
class PayState {
    constructor( cus ) {
        this.cus = cus
    }
    enter = () => {
        this.table = this.cus.cusInfo.table
        this.cusNode = document.querySelector(`.customer:nth-child(${this.table + 1})  .customer-item`)

        let iconFather = this.cusNode.children[0]
        let icon = iconFather.children[2]
        this.cusNode.className = 'customer-item customer-finish'
        if (icon) {
            iconFather.removeChild(icon)
        }
        iconFather.insertAdjacentHTML('beforeend', `
            <img class="customer-icon customer-money" src="./img/icon_money.png" alt="">
        `)
        this.cusNode.children[0].onclick = () => {
            this.cusNode.children[0].innerHTML = ''
            this.cusNode.className = 'customer-item'
            tables[this.table]= true
            this.cus.destory()
        }
    }
    leave = () => {}
}
class Customer {
    constructor( menuHandler) {
        this.waitState = new WaitState( this )
        this.orderState = new OrderState( this, menuHandler )
        this.serveState = new ServeState( this )
        this.eatState = new EatState( this )
        this.comfortState = new ComfortState( this )
        this.payState = new PayState( this )
        this.cusInfo = null
        this.curState = null
    }
    init(name, avatar) {
        this.cusInfo = {
            name,
            avatar,
            timeToLeave: 100, // 用户最多等待 100 min
            money: 0,
            table: -1,
            ordered: [],
            waitList: [
                // {
                //     dishID: 1,
                //     timeToLeave: 200
                // }
            ],
            eatList: [
                // {
                //     dishID: 1,
                //     timeToLeave: 200
                // }
            ],
            missList: [
                //dishID
            ],
            finishList: [],
            needPay: 0
        }
        this.curState = this.waitState
        this.waitState.enter()
    }
    setState(newState) {
        this.curState.leave()
        this.curState = newState
        this.curState.enter()
    }
    destory() {
        cusSet.delete(this)
    }
}




class MenuHandler {
    constructor() {
        this.tipMenu = document.querySelector('.tip-menu')
        this.mask = document.querySelector('.mask')
        this.lists = document.getElementsByName('menu')
        this.menuHeader = document.querySelector('.menu-header')

        for (let list of this.lists) {
            list.addEventListener('click', this.handleOrder)
        }
    }
    show = (name, avatar) => {
        this.name = name
        // 渲染菜单头部
        this.menuHeader.innerHTML = `
            <img src="${avatar}" alt="">
            <h3>${name}正在点菜，已点0元的菜</h3>
        `
        this.clear()
        this.tipMenu.style.display = 'block'
        this.mask.style.display = 'block'
    }
    close = () => {
        this.tipMenu.style.display = 'none'
        this.mask.style.display = 'none'
    }
    clear = () => {
        for (let list of this.lists) {
            list.checked = false
        }
    }
    check = () => {
        let coldDishes = 0,
            mainDishes = 0,
            drinking = 0;
        for (let i in this.lists) {
            if (i < 2) { //凉菜
                if (this.lists[i].checked === true) {
                    coldDishes++;
                }
            } else if (i < 7) { //主菜
                if (this.lists[i].checked === true) {
                    mainDishes++;
                }
            } else { //饮品
                if (this.lists[i].checked === true) {
                    drinking++;
                }
            }
        }
        if (coldDishes <= 1 && mainDishes === 1 && drinking <= 1) {
            return true;
        }
        return false;
    }
    statistics = () => {
        let ordered = []
        for (let i = 0; i < this.lists.length; i++) {
            if (this.lists[i].checked) {
                ordered.push(i)
            }
        }
        return {ordered}
    }
    handleOrder = () => {
        let totalPrice = 0;
        const orderConfirm = document.querySelector(".tip-menu-confirm");
        const orderText = document.querySelector('.menu-header h3')

        for (let i in this.lists) {
            if (this.lists[i].checked === true) {
                totalPrice += parseInt(this.lists[i].value);
            }
        }
        let text = `${this.name}正在点菜，已点${totalPrice}元的菜`;
        orderText.innerHTML = text;
        if (this.check()) {
            orderConfirm.setAttribute("style", "background: linear-gradient(180deg, #ffe699 50%, #ffd24d 50%);border: 3px solid #a2811d;color: #a2811d;");
        } else {
            orderConfirm.setAttribute("style", "background: linear-gradient(180deg, #ded3ba 50%, #d3c6a5 50%);border: 3px solid #938867;color: #938867;");
        }
    }
}




class GameInfo {
    constructor() {
        this.dateNode = document.querySelector('.info-date')
        this.moneyNode = document.querySelector('.info-money')
    }
    renderDate(week, day) {
        this.dateNode.innerHTML = `W${week} D${day}`
    }
    renderMoney(money) {
        this.moneyNode.innerText = `${money}`
    }
}

class GlobalClock {
    constructor(gameInfo) {
        this.week = 1
        this.day = 1
        this.minute = 0
        this.interval = null // 定时任务，更新时间
        this.gameInfo = gameInfo
    }
    startClock(fn) {
        this.interval = setInterval(() => {
            // 执行其他事件
            fn()
            // 每经过1440min，天数+1
            // 1min 对应实际的 100ms
            this.minute++
            if (this.minute > 1440) {
                this.day++
                this.minute = 0
                if (this.day > 7) {
                    this.week++
                    this.day = 1
                }
                this.gameInfo.renderDate(this.week, this.day)
            }
        }, 100)
    }
    stopClock() {
        if (this.interval) { clearInterval(this.interval) }
        this.interval = null
    }
}




const mask = document.querySelector('.mask')
const tipWel = document.querySelector('.tip-welcome')

const cusSet = new Set()

function startGame() {
    tipWel.style.display = 'none'
    mask.style.display = 'none'

    const gameInfo = new GameInfo()
    const globalClock = new GlobalClock(gameInfo)
    const menuHandler = new MenuHandler()


    const waitNum = 0
    const serveNum = 0
    // restaurant.addChef()

    // 全局时钟驱动顾客状态变化
    globalClock.startClock(() => {
        if (globalClock.minute % 20 === 0 && waitNum < 5){
            // 随机创建顾客信息
            let cus = new Customer(menuHandler)
            let idx = Math.floor(Math.random() * 7);
            let {name, avatar} = cusCandidate[idx]
            cusSet.add(cus)
            cus.init(name,avatar)
        }
        for (let cusItem of cusSet.values()) {
            if(cusItem.curState.run) {
                cusItem.curState.run()
            }
        }
        // for (let chefItem of restaurant.chefs) {
        //     chefItem.curState.run()
        // }
    })
}

tipWel.addEventListener('click', startGame)


